package com.yupi.springbootinit.service.impl;

import cn.hutool.core.lang.Pair;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.config.RedisUtils;
import com.yupi.springbootinit.constant.RedisConstant;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.mapper.UserMapper;
import com.yupi.springbootinit.model.entity.Orders;
import com.yupi.springbootinit.model.entity.Teachers;
import com.yupi.springbootinit.model.entity.Temporaryorders;
import com.yupi.springbootinit.model.enums.UserRoleEnum;
import com.yupi.springbootinit.model.vo.LoginTeacherVO;
import com.yupi.springbootinit.service.OrdersService;
import com.yupi.springbootinit.service.TeachersService;
import com.yupi.springbootinit.mapper.TeachersMapper;
import com.yupi.springbootinit.service.TemporaryordersService;
import com.yupi.springbootinit.utils.AlgorithmUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.xmlbeans.impl.xb.xsdschema.Attribute;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.*;
import java.util.stream.Collectors;

import static com.yupi.springbootinit.constant.UserConstant.USER_LOGIN_STATE;

/**
* @author zjb13
* @description 针对表【teachers(教师)】的数据库操作Service实现
* @createDate 2024-11-28 22:39:31
*/
@Service
public class TeachersServiceImpl extends ServiceImpl<TeachersMapper, Teachers>
    implements TeachersService{

    /**
     * 盐值，混淆密码
     */
    public static final String SALT = "yupi";

    @Resource
    private UserMapper userMapper ;

    @Resource
    private TeachersMapper teachersMapper;


    @Resource
    private TemporaryordersService temporaryordersService;

    @Resource
    private OrdersService ordersService;

    @Resource
    private RedisUtils redisUtils;

    @Override
    public LoginTeacherVO userLogin(String userAccount, String userPassword, HttpServletRequest request) {
        // 1. 校验
        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号错误");
        }
        if (userPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误");
        }
        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        // 查询用户是否存在
        QueryWrapper<Teachers> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        queryWrapper.eq("userPassword", encryptPassword);
        Teachers user = this.baseMapper.selectOne(queryWrapper);
        // 用户不存在
        if (user == null) {
            log.error("用户不存在");
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
        }
        // 3. 记录用户的登录态
        request.getSession().setAttribute(USER_LOGIN_STATE, user);
        // 4.存入Redis
        String userRole = user.getUserRole();
        String redisKey = UserRoleEnum.TEACHER.getValue()+user.getId();
        redisUtils.setex(redisKey,user, RedisConstant.REDIS_KEY_EXPIRES_ONE_MIN*10);
        return this.getLoginUserVO(user);
    }

    @Override
    public Teachers getLoginUser(HttpServletRequest request) {
        // 先判断是否已登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        Teachers currentUser = (Teachers) userObj;
        if (currentUser == null || currentUser.getId() == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        // 从数据库查询（追求性能的话可以注释，直接走缓存）
        long userId = currentUser.getId();
        currentUser = this.getById(userId);
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return currentUser;
    }

    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword) {
        // 1. 校验
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");
        }
        if (userPassword.length() < 8 || checkPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
        }
        // 密码和校验密码相同
        if (!userPassword.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        synchronized (userAccount.intern()) {
            // 账户不能重复
            QueryWrapper<Teachers> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userAccount", userAccount);
            long count = this.baseMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
            }
            // 2. 加密
            String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
            // 3. 插入数据
            Teachers user = new Teachers();
            user.setUserAccount(userAccount);
            user.setUserPassword(encryptPassword);
            user.setUserRole("teacher");
            boolean saveResult = this.save(user);
            if (!saveResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败，数据库错误");
            }
            return user.getId();
        }
    }

    @Override
    public List<Teachers> searchUsersByTags(List<String> tagNameList) {
        if (CollectionUtils.isEmpty(tagNameList)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
//        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//        // 拼接 and 查询
//        // like '%Java%' and like '%Python%'
//        for (String tagName : tagNameList) {
//            queryWrapper = queryWrapper.like("tags", tagName);
//        }
//        List<User> userList = userMapper.selectList(queryWrapper);
//        return userList.stream().map(this::getSafetyUser).collect(Collectors.toList());
        // 1. 先查询所有用户
        QueryWrapper<Teachers> queryWrapper = new QueryWrapper<>();
        List<Teachers> userList = teachersMapper.selectList(queryWrapper);
        Gson gson = new Gson();
        // 2. 在内存中判断是否包含要求的标签
        return userList.stream().filter(user -> {
            String tagsStr = user.getTags();
            Set<String> tempTagNameSet = gson.fromJson(tagsStr, new TypeToken<Set<String>>() {
            }.getType());
            tempTagNameSet = Optional.ofNullable(tempTagNameSet).orElse(new HashSet<>());
            for (String tagName : tagNameList) {
                if (!tempTagNameSet.contains(tagName)) {
                    return false;
                }
            }
            return true;
        }).map(this::getSafetyUser).collect(Collectors.toList());
    }

    @Override
    public boolean deleteTempOrder(long id, Teachers loginUser) {
        QueryWrapper<Temporaryorders> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        Long userId = loginUser.getId();
        queryWrapper.eq("teacherId", userId);
        return temporaryordersService.remove(queryWrapper);
    }

    @Override
    public List<Orders> matchOrders(long num, Teachers loginUser) {
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        String subjects = loginUser.getSubject();
        String[] userSubjects = subjects.split(",");
        List<String> userSubjectsList = Arrays.asList(userSubjects);
        queryWrapper.select("orderId", "subjects");
        queryWrapper.isNotNull("subjects");
        queryWrapper.eq("orderStatus", 0);
        List<Orders> ordersList = ordersService.list(queryWrapper);
        // 用户列表的下标 => 相似度
        List<Pair<Orders, Long>> list = new ArrayList<>();
        for (Orders orders : ordersList) {
            String[] allSubjectArray = orders.getSubjects().split(",");
            List<String> orderslist = Arrays.asList(allSubjectArray);
            long distance = AlgorithmUtils.minDistance(orderslist, userSubjectsList);
            list.add(new Pair<>(orders, distance));
        }
        // 按编辑距离由小到大排序
        List<Pair<Orders, Long>> topUserPairList = list.stream()
                .sorted((a, b) -> (int) (a.getValue() - b.getValue()))
                .limit(num)
                .collect(Collectors.toList());
        // 原本顺序的 orderId 列表
        List<Long> orderIdList = topUserPairList.stream().map(pair -> pair.getKey().getOrderId()).collect(Collectors.toList());
        QueryWrapper<Orders> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.in("orderId", orderIdList);
        // 1, 3, 2
        // User1、User2、User3
        // 1 => User1, 2 => User2, 3 => User3
        Map<Long, List<Orders>> userIdUserListMap = ordersService.list(userQueryWrapper)
                .stream()
                .collect(Collectors.groupingBy(Orders::getOrderId));
        List<Orders> finalUserList = new ArrayList<>();
        for (Long orderId : orderIdList) {
            finalUserList.add(userIdUserListMap.get(orderId).get(0));
        }
        return finalUserList;
    }

    @Override
    public Boolean confirmOrder(long id, Teachers loginUser) {
        Orders order = ordersService.getById(id);
        if (order == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (!order.getTeacherId().equals(loginUser.getId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        //判断是不是在上课中
        Integer orderStatus = order.getOrderStatus();
        if (orderStatus != 3) {
            return false;
        }
        Integer lastLessonCount = order.getLastLessonCount();
        //如果还有剩余上课次数,减少次数，更新状态
        if (lastLessonCount > 1) {
            lastLessonCount--;
            order.setLastLessonCount(lastLessonCount);
            order.setOrderStatus(1);
            return ordersService.updateById(order);
        }
        //如果已经没有剩余次数，更新状态为已完成，教师订单数+1
        // TODO: 2024/12/1 如果添加支付功能，则把订单状态改成待支付，支付完才已完成
        Integer ordersTime = loginUser.getOrdersTime();
        loginUser.setOrdersTime(ordersTime + 1);
        this.updateById(loginUser);
        order.setLastLessonCount(0);
        order.setOrderStatus(2);
        Integer lessonCount = order.getLessonCount();
        Double lessonPrice = order.getLessonPrice();
        //更新订单总金额
        order.setTransactionAmount(lessonCount * lessonPrice);
        return ordersService.updateById(order);
    }

    @Override
    public void updateRate(int rate, Teachers teachers) {
        Double overallRating = teachers.getOverallRating();
        Integer ordersTime = teachers.getOrdersTime();
        Double oldRate = overallRating * (ordersTime-1);
        overallRating = (oldRate + rate) / ordersTime;
        teachers.setOverallRating(overallRating);
        this.updateById(teachers);
    }

    @Override
    public void updateComment(Teachers teachers) {
        Long teacherId = teachers.getId();
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("teacherId", teacherId);
        queryWrapper.eq("orderStatus", 2);
        List<Orders> ordersList = ordersService.list(queryWrapper);

        // 使用流来获取每个Orders对象的userComments字段，并收集到一个列表中
        List<String> userCommentsList = ordersList.stream()
                .map(Orders::getUserComments) // 假设getUserComments()返回的是String类型的userComments
                .collect(Collectors.toList()); // 收集到List<String>中

        Gson gson = new Gson();
        String json = gson.toJson(userCommentsList); // 将userComments列表转换为JSON字符串
        teachers.setComments(json); // 设置teachers对象的comments属性
        this.updateById(teachers); // 更新teachers对象
    }


    @Override
    public LoginTeacherVO getLoginUserVO(Teachers user) {
        if (user == null) {
            return null;
        }
        LoginTeacherVO loginUserVO = new LoginTeacherVO();
        BeanUtils.copyProperties(user, loginUserVO);
        return loginUserVO;
    }

    @Override
    public Teachers getSafetyUser(Teachers originUser) {
        if (originUser == null) {
            return null;
        }
        Teachers safetyUser = new Teachers();
        safetyUser.setId(originUser.getId());
        safetyUser.setUserName(originUser.getUserName());
        safetyUser.setUserAccount(originUser.getUserAccount());
        safetyUser.setUserAvatar(originUser.getUserAvatar());
        safetyUser.setGender(originUser.getGender());
        safetyUser.setPhoneNumber(originUser.getPhoneNumber());
        safetyUser.setEmail(originUser.getEmail());
        safetyUser.setUserStatus(0);
        safetyUser.setCreateTime(originUser.getCreateTime());
        safetyUser.setUserRole(originUser.getUserRole());
        safetyUser.setTags(originUser.getTags());
        return safetyUser;
    }
}




